home *** CD-ROM | disk | FTP | other *** search
/ GFX Sensations 1 / Graphic Sensations - Volume 1.iso / tools / amiga / 3d_tools / irit40s.lha / Irit / cagd_lib / sbzr_aux.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-30  |  12.6 KB  |  402 lines

  1. /******************************************************************************
  2. * SBzr-Aux.c - Bezier surface auxilary routines.                  *
  3. *******************************************************************************
  4. * Written by Gershon Elber, July. 90.                          *
  5. ******************************************************************************/
  6.  
  7. #include <ctype.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include "cagd_loc.h"
  11.  
  12. /* Define some marcos to make some of the routines below look better. They  */
  13. /* calculate the index of the U, V point of the control mesh in Points.        */
  14. #define DERIVED_SRF(U, V)    CAGD_MESH_UV(DerivedSrf, U, V)
  15. #define RAISED_SRF(U, V)    CAGD_MESH_UV(RaisedSrf, U, V)
  16. #define SRF(U, V)        CAGD_MESH_UV(Srf, U, V)
  17.  
  18. static CagdSrfStruct *CnvrtBspline2BezierSrfAux(CagdSrfStruct *Srf);
  19.  
  20. /******************************************************************************
  21. * Given a bezier surface - subdivide it into two at given parametric value.   *
  22. * Returns pointer to first surface in a list of two srfs (subdivided ones).   *
  23. * The subdivision is exact result of subdivising the surface one row/col at a *
  24. * time, using the Bezier curve subdivision.                      *
  25. ******************************************************************************/
  26. CagdSrfStruct *BzrSrfSubdivAtParam(CagdSrfStruct *Srf, CagdRType t,
  27.                             CagdSrfDirType Dir)
  28. {
  29.     int Row, Col,
  30.     ULength = Srf -> ULength,
  31.     VLength = Srf -> VLength;
  32.     CagdCrvStruct *Crv, *LCrv, *RCrv;
  33.     CagdSrfStruct
  34.     *RSrf = BzrSrfNew(ULength, VLength, Srf ->PType),
  35.     *LSrf = BzrSrfNew(ULength, VLength, Srf ->PType);
  36.  
  37.     switch (Dir) {
  38.     case CAGD_CONST_U_DIR:
  39.         for (Row = 0; Row < VLength; Row++) {
  40.         Crv = BzrSrfCrvFromMesh(Srf, Row, CAGD_CONST_V_DIR);
  41.         LCrv = BzrCrvSubdivAtParam(Crv, t);
  42.         RCrv = LCrv -> Pnext;
  43.         CagdCrvToMesh(LCrv, Row, CAGD_CONST_V_DIR, LSrf);
  44.         CagdCrvToMesh(RCrv, Row, CAGD_CONST_V_DIR, RSrf);
  45.  
  46.         CagdCrvFree(Crv);
  47.         CagdCrvFree(LCrv);
  48.         CagdCrvFree(RCrv);
  49.         }
  50.         break;
  51.     case CAGD_CONST_V_DIR:
  52.         for (Col = 0; Col < ULength; Col++) {
  53.         Crv = BzrSrfCrvFromMesh(Srf, Col, CAGD_CONST_U_DIR);
  54.         LCrv = BzrCrvSubdivAtParam(Crv, t);
  55.         RCrv = LCrv -> Pnext;
  56.         CagdCrvToMesh(LCrv, Col, CAGD_CONST_U_DIR, LSrf);
  57.         CagdCrvToMesh(RCrv, Col, CAGD_CONST_U_DIR, RSrf);
  58.  
  59.         CagdCrvFree(Crv);
  60.         CagdCrvFree(LCrv);
  61.         CagdCrvFree(RCrv);
  62.         }
  63.         break;
  64.     default:
  65.         FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  66.         break;
  67.     }
  68.  
  69.     LSrf -> Pnext = RSrf;
  70.     return LSrf;
  71. }
  72.  
  73. /******************************************************************************
  74. * Return a new surface, identical to the original but with one degree higher  *
  75. * in the given direction.                              *
  76. * Let old control polygon be P(i), i = 0 to k-1, and Q(i) be new one then:    *
  77. *               i        k-i                          *
  78. * Q(0) = P(0), Q(i) = --- P(i-1) + (---) P(i), Q(k) = P(k-1).              *
  79. *               k         k                          *
  80. * This is applied to all rows/cols of the surface.                  *
  81. ******************************************************************************/
  82. CagdSrfStruct *BzrSrfDegreeRaise(CagdSrfStruct *Srf, CagdSrfDirType Dir)
  83. {
  84.     CagdBType
  85.     IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
  86.     int i, j, Row, Col,
  87.     ULength = Srf -> ULength,
  88.     VLength = Srf -> VLength,
  89.     MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType);
  90.     CagdSrfStruct
  91.     *RaisedSrf = NULL;
  92.  
  93.     switch (Dir) {
  94.     case CAGD_CONST_U_DIR:
  95.         RaisedSrf = BzrSrfNew(ULength, VLength + 1, Srf -> PType);
  96.  
  97.         for (Col = 0; Col < ULength; Col++) {
  98.         for (j = IsNotRational; j <= MaxCoord; j++)        /* Q(0). */
  99.             RaisedSrf -> Points[j][RAISED_SRF(Col, 0)] =
  100.                Srf -> Points[j][SRF(Col, 0)];
  101.  
  102.         for (i = 1; i < VLength; i++)                /* Q(i). */
  103.             for (j = IsNotRational; j <= MaxCoord; j++)
  104.             RaisedSrf -> Points[j][RAISED_SRF(Col, i)] =
  105.                 Srf -> Points[j][SRF(Col, i - 1)] *
  106.                                  (i / ((CagdRType) VLength)) +
  107.                 Srf -> Points[j][SRF(Col, i)] *
  108.                      ((VLength - i) / ((CagdRType) VLength));
  109.  
  110.         for (j = IsNotRational; j <= MaxCoord; j++)        /* Q(k). */
  111.             RaisedSrf -> Points[j][RAISED_SRF(Col, VLength)] =
  112.             Srf -> Points[j][SRF(Col, VLength - 1)];
  113.             }
  114.         break;
  115.     case CAGD_CONST_V_DIR:
  116.         RaisedSrf = BzrSrfNew(ULength + 1, VLength, Srf -> PType);
  117.  
  118.         for (Row = 0; Row < VLength; Row++) {
  119.         for (j = IsNotRational; j <= MaxCoord; j++)        /* Q(0). */
  120.             RaisedSrf -> Points[j][RAISED_SRF(0, Row)] =
  121.                Srf -> Points[j][SRF(0, Row)];
  122.  
  123.         for (i = 1; i < ULength; i++)                /* Q(i). */
  124.             for (j = IsNotRational; j <= MaxCoord; j++)
  125.             RaisedSrf -> Points[j][RAISED_SRF(i, Row)] =
  126.                 Srf -> Points[j][SRF(i - 1, Row)] *
  127.                                  (i / ((CagdRType) ULength)) +
  128.                 Srf -> Points[j][SRF(i, Row)] *
  129.                          ((ULength - i) / ((CagdRType) ULength));
  130.  
  131.         for (j = IsNotRational; j <= MaxCoord; j++)        /* Q(k). */
  132.             RaisedSrf -> Points[j][RAISED_SRF(ULength, Row)] =
  133.             Srf -> Points[j][SRF(ULength - 1, Row)];
  134.         }
  135.         break;
  136.     default:
  137.         FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  138.         break;
  139.     }
  140.  
  141.     return RaisedSrf;
  142. }
  143.  
  144. /******************************************************************************
  145. * Return a new surface equal to the derived surface in the direction Dir.     *
  146. * Let old control polygon be P(i), i = 0 to k-1, and Q(i) be new one then:    *
  147. * Q(i) = (k - 1) * P(i+1) - P(i), i = 0 to k-2.                      *
  148. * This is applied to all rows/cols of the surface.                  *
  149. ******************************************************************************/
  150. CagdSrfStruct *BzrSrfDerive(CagdSrfStruct *Srf, CagdSrfDirType Dir)
  151. {
  152.     CagdBType
  153.     IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
  154.     int i, j, Row, Col,
  155.     ULength = Srf -> ULength,
  156.     VLength = Srf -> VLength,
  157.     MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType);
  158.     CagdSrfStruct
  159.         *DerivedSrf = NULL;
  160.  
  161.     if (!IsNotRational)
  162.     return BzrSrfDeriveRational(Srf, Dir);
  163.  
  164.     switch (Dir) {
  165.     case CAGD_CONST_U_DIR:
  166.         if (VLength < 2)
  167.         FATAL_ERROR(CAGD_ERR_LIN_NO_SUPPORT);
  168.  
  169.         DerivedSrf = BzrSrfNew(ULength, VLength - 1, Srf -> PType);
  170.  
  171.         for (Col = 0; Col < ULength; Col++)
  172.         for (i = 0; i < VLength - 1; i++)
  173.             for (j = IsNotRational; j <= MaxCoord; j++)
  174.             DerivedSrf -> Points[j][DERIVED_SRF(Col, i)] =
  175.                             (VLength - 1) *
  176.                 (Srf -> Points[j][SRF(Col, i + 1)] -
  177.                  Srf -> Points[j][SRF(Col, i)]);
  178.         break;
  179.     case CAGD_CONST_V_DIR:
  180.         if (ULength < 2)
  181.         FATAL_ERROR(CAGD_ERR_LIN_NO_SUPPORT);
  182.  
  183.         DerivedSrf = BzrSrfNew(ULength - 1, VLength, Srf -> PType);
  184.  
  185.         for (Row = 0; Row < VLength; Row++)
  186.         for (i = 0; i < ULength - 1; i++)
  187.             for (j = IsNotRational; j <= MaxCoord; j++)
  188.             DerivedSrf -> Points[j][DERIVED_SRF(i, Row)] =
  189.                             (ULength - 1) *
  190.                 (Srf -> Points[j][SRF(i + 1, Row)] -
  191.                  Srf -> Points[j][SRF(i, Row)]);
  192.         break;
  193.     default:
  194.         FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  195.         break;
  196.     }
  197.  
  198.     return DerivedSrf;
  199. }
  200.  
  201.  
  202. /******************************************************************************
  203. * Evaluate the tangent to a surface at a given point and given direction.     *
  204. ******************************************************************************/
  205. CagdVecStruct *BzrSrfTangent(CagdSrfStruct *Srf, CagdRType u, CagdRType v,
  206.                              CagdSrfDirType Dir)
  207. {
  208.     CagdVecStruct
  209.     *Tangent = NULL;
  210.     CagdCrvStruct *Crv;
  211.  
  212.     switch (Dir) {
  213.     case CAGD_CONST_V_DIR:
  214.         Crv = BzrSrfCrvFromSrf(Srf, v, Dir);
  215.         Tangent = BzrCrvTangent(Crv, u);
  216.         CagdCrvFree(Crv);
  217.         break;
  218.     case CAGD_CONST_U_DIR:
  219.         Crv = BzrSrfCrvFromSrf(Srf, u, Dir);
  220.         Tangent = BzrCrvTangent(Crv, v);
  221.         CagdCrvFree(Crv);
  222.         break;
  223.     default:
  224.         FATAL_ERROR(CAGD_ERR_DIR_NOT_CONST_UV);
  225.         break;
  226.     }
  227.  
  228.     return Tangent;
  229. }
  230.  
  231. /******************************************************************************
  232. * Evaluate the normal of a surface at a given point.                  *
  233. * If we fail to compute the normal at given location we try by moving a tad.  *
  234. ******************************************************************************/
  235. CagdVecStruct *BzrSrfNormal(CagdSrfStruct *Srf, CagdRType u, CagdRType v)
  236. {
  237.     static CagdVecStruct Normal;
  238.     CagdVecStruct *V, T1, T2;
  239.  
  240.     V = BzrSrfTangent(Srf, u, v, CAGD_CONST_U_DIR);
  241.     if (CAGD_LEN_VECTOR(*V) < EPSILON)
  242.     V = BzrSrfTangent(Srf,
  243.               u > 0.5 ? u - EPSILON : u + EPSILON,
  244.               v > 0.5 ? v - EPSILON : v + EPSILON,
  245.               CAGD_CONST_U_DIR);
  246.     CAGD_COPY_VECTOR(T1, *V);
  247.  
  248.     V = BzrSrfTangent(Srf, u, v, CAGD_CONST_V_DIR);
  249.     if (CAGD_LEN_VECTOR(*V) < EPSILON)
  250.     V = BzrSrfTangent(Srf,
  251.               u > 0.5 ? u - EPSILON : u + EPSILON,
  252.               v > 0.5 ? v - EPSILON : v + EPSILON,
  253.               CAGD_CONST_V_DIR);
  254.     CAGD_COPY_VECTOR(T2, *V);
  255.  
  256.     /* The normal is the cross product of T1 and T2: */
  257.     Normal.Vec[0] = T1.Vec[1] * T2.Vec[2] - T1.Vec[2] * T2.Vec[1];
  258.     Normal.Vec[1] = T1.Vec[2] * T2.Vec[0] - T1.Vec[0] * T2.Vec[2];
  259.     Normal.Vec[2] = T1.Vec[0] * T2.Vec[1] - T1.Vec[1] * T2.Vec[0];
  260.  
  261.     CAGD_NORMALIZE_VECTOR(Normal);            /* Normalize the vector. */
  262.  
  263.     return &Normal;
  264. }
  265.  
  266. /******************************************************************************
  267. * Convert a Bezier srf into Bspline srf by adding two open knot vectors.      *
  268. ******************************************************************************/
  269. CagdSrfStruct *CnvrtBezier2BsplineSrf(CagdSrfStruct *Srf)
  270. {
  271.     CagdSrfStruct *BspSrf;
  272.  
  273.     if (Srf -> GType != CAGD_SBEZIER_TYPE) {
  274.     FATAL_ERROR(CAGD_ERR_WRONG_SRF);
  275.     return NULL;
  276.     }
  277.  
  278.     BspSrf = CagdSrfCopy(Srf);
  279.  
  280.     BspSrf -> UOrder = BspSrf -> ULength;
  281.     BspSrf -> VOrder = BspSrf -> VLength;
  282.     BspSrf -> UKnotVector = BspKnotUniformOpen(BspSrf -> ULength,
  283.                             BspSrf -> UOrder, NULL);
  284.     BspSrf -> VKnotVector = BspKnotUniformOpen(BspSrf -> VLength,
  285.                             BspSrf -> VOrder, NULL);
  286.     BspSrf -> GType = CAGD_SBSPLINE_TYPE;
  287.     return BspSrf;
  288. }
  289.  
  290. /******************************************************************************
  291. * Convert a Bspline srf into a set of Bezier srfs by subdiving the Bspline    *
  292. * surface at all its internal knots.                          *
  293. *   Returned is a list of Bezier surface.                      *
  294. ******************************************************************************/
  295. CagdSrfStruct *CnvrtBspline2BezierSrf(CagdSrfStruct *Srf)
  296. {
  297.     int i,
  298.     UOrder = Srf -> UOrder,
  299.     ULength = Srf -> ULength;
  300.     CagdRType LastT,
  301.     *UKnotVector = Srf -> UKnotVector;
  302.     CagdSrfStruct *BezierSrfsAux, *TSrf,
  303.     *BezierSrfs = NULL,
  304.     *OrigSrf = Srf;
  305.  
  306.     if (Srf -> GType != CAGD_SBSPLINE_TYPE) {
  307.     FATAL_ERROR(CAGD_ERR_WRONG_SRF);
  308.     return NULL;
  309.     }
  310.  
  311.     for (i = ULength - 1, LastT = UKnotVector[ULength]; i >= UOrder; i--) {
  312.         CagdRType
  313.             t = UKnotVector[i];
  314.             
  315.     if (!APX_EQ(LastT, t)) {
  316.             CagdSrfStruct
  317.             *Srfs = BspSrfSubdivAtParam(Srf, t, CAGD_CONST_U_DIR);
  318.  
  319.             if (Srf != OrigSrf)
  320.                 CagdSrfFree(Srf);
  321.  
  322.         BezierSrfsAux = CnvrtBspline2BezierSrfAux(Srfs -> Pnext);
  323.         for (TSrf = BezierSrfsAux; TSrf -> Pnext != NULL; TSrf = TSrf -> Pnext);
  324.         TSrf -> Pnext = BezierSrfs;
  325.         BezierSrfs = BezierSrfsAux;
  326.         CagdSrfFree(Srfs -> Pnext);
  327.  
  328.             Srf = Srfs;
  329.             Srf -> Pnext = NULL;
  330.         }
  331.     }
  332.  
  333.     if (Srf == OrigSrf)
  334.     BezierSrfs = CnvrtBspline2BezierSrfAux(Srf);
  335.     else {
  336.     BezierSrfsAux = CnvrtBspline2BezierSrfAux(Srf);
  337.     for (TSrf = BezierSrfsAux; TSrf -> Pnext != NULL; TSrf = TSrf -> Pnext);
  338.     TSrf -> Pnext = BezierSrfs;
  339.     BezierSrfs = BezierSrfsAux;
  340.  
  341.     CagdSrfFree(Srf);
  342.     }
  343.  
  344.     return BezierSrfs;
  345. }
  346.  
  347.  
  348. /******************************************************************************
  349. * Aux. function to CnvrtBspline2BezierSrf. Does the other subdivision.          *
  350. ******************************************************************************/
  351. static CagdSrfStruct *CnvrtBspline2BezierSrfAux(CagdSrfStruct *Srf)
  352. {
  353.     int i,
  354.     VOrder = Srf -> VOrder,
  355.     VLength = Srf -> VLength;
  356.     CagdRType LastT,
  357.     *VKnotVector = Srf -> VKnotVector;
  358.     CagdSrfStruct
  359.     *BezierSrfs = NULL,
  360.     *OrigSrf = Srf;
  361.  
  362.     for (i = VLength - 1, LastT = VKnotVector[VLength]; i >= VOrder; i--) {
  363.         CagdRType
  364.             t = VKnotVector[i];
  365.             
  366.     if (!APX_EQ(LastT, t)) {
  367.             CagdSrfStruct
  368.             *Srfs = BspSrfSubdivAtParam(Srf, t, CAGD_CONST_V_DIR);
  369.  
  370.             if (Srf != OrigSrf)
  371.                 CagdSrfFree(Srf);
  372.  
  373.             Srfs -> Pnext -> Pnext = BezierSrfs;
  374.         BezierSrfs = Srfs -> Pnext;
  375.  
  376.             Srf = Srfs;
  377.             Srf -> Pnext = NULL;
  378.         }
  379.     }
  380.  
  381.     if (Srf == OrigSrf) {
  382.     /* No interior knots in this surface - just copy it: */
  383.         BezierSrfs = CagdSrfCopy(Srf);
  384.     }
  385.     else {
  386.         Srf -> Pnext = BezierSrfs;
  387.         BezierSrfs = Srf;
  388.     }
  389.  
  390.     for (Srf = BezierSrfs; Srf != NULL; Srf = Srf -> Pnext) {
  391.         Srf -> GType = CAGD_SBEZIER_TYPE;
  392.     IritFree((VoidPtr) Srf -> UKnotVector);
  393.     IritFree((VoidPtr) Srf -> VKnotVector);
  394.     Srf -> UKnotVector = NULL;
  395.     Srf -> VKnotVector = NULL;
  396.     }
  397.     
  398.     return BezierSrfs;
  399. }
  400.  
  401.  
  402.